﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebRole1.Search.Query;

namespace Microsoft.WindowsAzure.Search
{
    public class Rank
    {
        public static double[] ComputeCosine(Dictionary<String, Entry> dictionary, double[] lengths, List<String>queryTerms)
        {
            int docNum = lengths.Length;

            // cosine score
            double[] scores = new double[docNum];

            for (int i = 0; i < docNum; i++)
                scores[i] = 0;

            // compute tf-idf score
            foreach (String term in queryTerms)
            {
                if (dictionary.ContainsKey(term))
                {
                    Entry entry = dictionary[term];
                    // keyword exists in index dictionary
                    double idf = Math.Log10((double)docNum / (double)entry.DocFreq);

                    foreach (Posting posting in entry.Posting_list)
                    {
                        scores[posting.DocID] += idf * posting.TermFreq;
                    }
                }
            }

            // normalize to cosine score
            for (int i = 0; i < docNum; i++)
            {
                if (lengths[i] != 0)
                    scores[i] /= lengths[i];
            }

            return scores;
        }

        public static List<String> GetTopRankDocs(Dictionary<int, double> scoreDic, String[] docLines)
        {
            // LinQ, get top 10 documents
            // result => <docID, score>
            var result = from pair in scoreDic.OrderByDescending(score => score.Value).Take(10) select pair;

            // <docID, url>
            Dictionary<int, String> docDir = new Dictionary<int, String>();

            foreach (KeyValuePair<int, double> pair in result)
            {
                // remove documents with score 0
                if (pair.Value > 0)
                    docDir.Add(pair.Key, "");
            }

            // traverse docInfo to get url mapping with docID
            int d = 0;
            for (int i = 1; i < docLines.Length && d < docDir.Keys.Count; i++)
            {
                String[] docMapLine = Tokenizer.CommaTokenize(docLines[i]);
                int docID = Convert.ToInt32(docMapLine[0]);
                String docPath = docMapLine[2];

                if (docDir.ContainsKey(docID))
                {
                    docDir[docID] = docPath;
                    d++;
                }
            }

            // result documents url
            List<String> resultDoc = new List<String>();
            foreach (KeyValuePair<int, String> pair in docDir)
            {
                resultDoc.Add(pair.Value);
            }

            return resultDoc;
        }

        public static List<String> GetTopRankDocs(Dictionary<int, double> scoreDic, DocInfoServiceContext context)
        {
            // LinQ, get top 10 documents
            // result => <docID, score>
            var result = from pair in scoreDic.OrderByDescending(score => score.Value).Take(10) select pair;

            // <docID, url>
            Dictionary<int, String> docDir = new Dictionary<int, String>();

            foreach (KeyValuePair<int, double> pair in result)
            {
                // remove documents with score 0
                if (pair.Value > 0){
                    IQueryable<DocInfo> info = context.Select(pair.Key);
                    String path = "";
                    if(info != null)
                    {
                        foreach(DocInfo doc in info)
                        {
                            path = doc.path;
                        }
                    }
                    docDir.Add(pair.Key, path);
                }
            }

            // traverse docInfo to get url mapping with docID
            /*int d = 0;
            for (int i = 1; i < docLines.Length && d < docDir.Keys.Count; i++)
            {
                String[] docMapLine = Tokenizer.CommaTokenize(docLines[i]);
                int docID = Convert.ToInt32(docMapLine[0]);
                String docPath = docMapLine[2];

                if (docDir.ContainsKey(docID))
                {
                    docDir[docID] = docPath;
                    d++;
                }
            }*/

            // result documents url
            List<String> resultDoc = new List<String>();
            foreach (KeyValuePair<int, String> pair in docDir)
            {
                resultDoc.Add(pair.Value);
            }

            return resultDoc;
        }
    }
}